
const Router = require('koa-router')
const { resolve } = require('path')
const glob = require('glob')
const _  = require('lodash')
const symbolPrefix = Symbol('prefix')

const routerMap = new Map()

const isArray = c => _.isArray(c) ? c : [c]
export class Route {
  constructor (app, apiPath) {
    this.app = app
    this.apiPath = apiPath
    this.router = new Router()
  }
  init () {
    glob.sync(resolve(this.apiPath, './**/*.js')).forEach(require);
    // require('../routes')
    // require('../routes/user')
    for (let [conf, controller] of routerMap) {
      // const constructors = isArray(controller)
      const constructors = controller
      let prefixPath = conf.target[symbolPrefix]
      if (prefixPath) prefixPath = normallizePath(prefixPath)
      const routerPath = prefixPath + conf.path
      this.router[conf.methods](routerPath, ...constructors)
    }
    this.app.use(this.router.routes())
    this.app.use(this.router.allowedMethods())
  }
}

const normallizePath = path => path.startsWith('/') ? path : `/${path}`

const router = conf => (target, key, descriptor) => {
  target[key] = isArray(target[key])
  conf.path = normallizePath(conf.path)
  routerMap.set({
    target,
    ...conf
  }, target[key])
}

export const controller = path => target => target.prototype[symbolPrefix] = path

const convert = middleware => (target, key, descriptor) => {
  target[key] = isArray(target[key])
  target[key].unshift(middleware)
}

export const Auth = convert(async (ctx, next) => {
  if (!ctx.session.user) {
    return (
      ctx.body = {
        success: false,
        errCode: 401,
        errMsg: '登陆信息或已失效, 请登陆'
      }
    )
  }
  await next()
})

export const get = path => router({
  methods: 'get',
  path: path
})

export const post = path => router({
  methods: 'post',
  path: path
})

export const put = path => router({
  methods: 'put',
  path: path
})

export const del = path => router({
  methods: 'delete',
  path: path
})

export const use = path => router({
  methods: 'use',
  path: path
})

export const all = path => router({
  methods: 'all',
  path: path
})
